#include "travls.h"

Population::Population(Map* m)
{
	map = m;
	generation = 0;
	for(int i=0;i<POP_SIZE;i++)
	{
		Individual c(m);
		pop[i] = c;
	}
}
Population::Population(Map* m, Population p)
{
	map = m;
	generation = 0;
	for(int i=0;i<POP_SIZE;i++)
	{
		pop[i] = p.pop[i];
	}
}
void Population::printStat()
{
	ofstream file ( "coord.txt", ios::app );
	double min, max, average=0;
	min = pop[0].getDistance();
	for (int j=0;j<CITY_NUM;j++)
	{
		best[j]=pop[0].getGenome(j);
	}
	max = pop[0].getDistance();
	for(int i=0;i<POP_SIZE;i++)
	{
		double tempDist = pop[i].getDistance();
		if(tempDist<min)
		{
			min = tempDist;
			for (int j=0;j<CITY_NUM;j++)
			{
				best[j]=pop[i].getGenome(j);
			}
		}
		if(tempDist>max)
			max = tempDist;
		average+= tempDist;
	}

	static int min_bar = (int) min;
	static int ave_bar = (int) average/POP_SIZE;
	int min_length = (int)(1.0*min/ave_bar * BAR_LENGTH);
	int ave_length = (int)(1.0*(average/POP_SIZE)/ave_bar * BAR_LENGTH);
	file << generation 
		<< "\t" << min 
		//	 << "\t" << max 
		<< "\t" << average/POP_SIZE << "  ";
	cout << setw(4) << generation 
		<< "\t" << setw(8) << setprecision(1) << min 
		//	 << "\t" << max 
		<< " " << setw(8) << setprecision(1) << average/POP_SIZE << "  ";
	for (int i=0;i < min_length; i++)
	{
		cout << "=";
	}
	for (int i=0;i < ave_length-min_length; i++)
	{
		cout << "+";
	}
	Coord * coords = map->getCoords();
	file << endl;

	double xPrint[CITY_NUM];
	double yPrint[CITY_NUM];
	for(int i=0;i<CITY_NUM;i++)
	{
		xPrint[i] = coords[best[i]].getX();
		yPrint[i] = coords[best[i]].getY();
	}

	//print x
	file << "x=[";
	for(int i=0;i<CITY_NUM;i++)
	{
		file << xPrint[i]/MAP_SIZE_X << ",";
	}
	file << xPrint[0]/MAP_SIZE_X << "]" << endl;
	//print y
	file << "y=[";
	for(int i=0;i<CITY_NUM;i++)
	{
		file << yPrint[i]/MAP_SIZE_Y << ",";
	}
	file << yPrint[0]/MAP_SIZE_Y << "]" << endl;

	file << endl;
	cout << endl;
	file.close();
}
void Population::nextGeneration(int swapAndInsert)
{
	generation++;
	Individual children[CHILD_SIZE];
	for(int i=0;i<CHILD_SIZE;i++)
	{
		//swap and insert
		if(swapAndInsert == 3)
		{
			Individual c=pop[i];
			if( (rand() % 100 +1) < SWAP_CHANCE)
			{
				c = c.swapGenome();
			}
			else
			{
				c = c.insertGenome();
			}
			children[i] = c;
		}

		//insert
		else if ( swapAndInsert == 2 )
		{
			Individual c = pop[i].insertGenome();
			children[i] = c;
		}

		//swap
		else if (swapAndInsert == 1)
		{
			Individual c = pop[i].swapGenome();
			children[i] = c;
		}

		//random
		else if (swapAndInsert == 0)
		{
			Individual c(map);
			children[i] = c;
		}
	}
	int elements = sizeof(children)/sizeof(children[0]);
	sort(children, children + elements);

	elements = sizeof(pop)/sizeof(pop[0]);
	sort(pop, pop + elements);

	int childIndex = 0;
	int popIndex = 0;

	Individual temp[POP_SIZE];
	int count =0;

	while(count < POP_SIZE )
	{
		if( childIndex > CHILD_SIZE ||(pop[popIndex] < children[childIndex] && popIndex < POP_SIZE-1) )
		{
			temp[count] = pop[popIndex++];
			count++;
		}
		else if ( childIndex < CHILD_SIZE -1)
		{
			temp[count] = children[childIndex++];
			count++;
		}
	}

	for(int i=0;i<POP_SIZE;i++)
	{
		pop[i] = temp[i];
	}
}

